home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / game / board / Chaos_src.lha / chaos / src / OutDWZ.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  10KB  |  424 lines

  1. /*  Chaos:                  The Chess HAppening Organisation System     V5.3
  2.     Copyright (C)   1993    Jochen Wiedmann
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.     $RCSfile: OutDWZ.c,v $
  20.     $Revision: 3.2 $
  21.     $Date: 1994/12/03 18:02:26 $
  22.  
  23.     This file contains the functions that compute and print the DWZ-ratings.
  24.  
  25.     Computer:   Amiga 1200                  Compiler:   Dice 2.07.54 (3.0)
  26.  
  27.     Author:     Jochen Wiedmann
  28.         Am Eisteich 9
  29.       72555 Metzingen
  30.         Tel. 07123 / 14881
  31.         Internet: jochen.wiedmann@zdv.uni-tuebingen.de
  32. */
  33.  
  34.  
  35. #ifndef CHAOS_H
  36. #include "chaos.h"
  37. #endif
  38.  
  39. #include <math.h>
  40. #include <time.h>
  41.  
  42.  
  43. #ifdef _DCC
  44. extern __far const int PercentToDWZTab[];
  45. #else
  46. #ifdef __SASC
  47. extern const int __far PercentToDWZTab[];
  48. #else
  49. extern const int PercentToDWZTab[];
  50. #endif
  51. #endif
  52. extern const double DWZtoPercentTab[];
  53.  
  54.  
  55. struct DWZ
  56.   { struct DWZ *Next;
  57.     struct Player *t;
  58.     short R0;
  59.     short Rn;
  60.     long  Rc;
  61.     double W;
  62.     double We;
  63.     short RH;
  64.     short E;
  65.     short J;
  66.     short n;
  67.   };
  68.  
  69.  
  70.  
  71.  
  72. /*
  73.     This converts a string into a tm structure. Why isn't this part of the
  74.     Dice library?
  75.  
  76.     Inputs: strptr  - pointer to the string to be converted
  77.         tmptr   - pointer to the tm structure where the result will be
  78.               stored
  79.  
  80.     Result: TRUE, if the string is valid, FALSE otherwise
  81.         (Only marginal checks are done)
  82. */
  83. int atotm(char *strptr, struct tm *tmptr)
  84.  
  85. { long mday, month, year;
  86.   int i;
  87.   static short daypermonth[] = {31,29,31,30,31,30,31,31,30,31,30,31};
  88.  
  89.   if ((i = StrToLong((STRPTR) strptr, &mday)) < 0  ||  strptr[i] == '\0')
  90.   { return(FALSE);
  91.   }
  92.   strptr = strptr+(i+1);
  93.   if ((i = StrToLong((STRPTR) strptr, &month)) < 0  ||  strptr[i] == '\0')
  94.   { return(FALSE);
  95.   }
  96.   strptr = strptr+(i+1);
  97.   if ((i = StrToLong((STRPTR) strptr, &year)) < 0)
  98.   { return(FALSE);
  99.   }
  100.   if (year < 1  ||  month < 1  ||  month > 12  ||
  101.       mday < 1  ||  mday > daypermonth[month-1])
  102.   { return(FALSE);
  103.   }
  104.   if (year<100)
  105.   { year+=1900;
  106.   }
  107.   tmptr->tm_year = year-1900;
  108.   tmptr->tm_mon = month-1;
  109.   tmptr->tm_mday = mday;
  110.   return(TRUE);
  111. }
  112.  
  113.  
  114.  
  115.  
  116. /*
  117.     The following function compares two dates.
  118.  
  119.     Inputs: tm1, tm2: pointer to tm structures
  120.  
  121.     Result: <0 : tm1 < tm2
  122.         =0 : tm1 = tm2
  123.         >0 : tm1 > tm2
  124. */
  125. static int CmpDates(struct tm *tm1, struct tm *tm2)
  126.  
  127. {
  128.   if (tm1->tm_year != tm2->tm_year)
  129.   { return(tm1->tm_year - tm2->tm_year);
  130.   }
  131.   if (tm1->tm_mon != tm2->tm_mon)
  132.   { return(tm1->tm_mon - tm2->tm_mon);
  133.   }
  134.   return(tm1->tm_mday - tm2->tm_mday);
  135. }
  136.  
  137.  
  138.  
  139.  
  140. /*
  141.     The following function computes the mean value in points corresponding
  142.     to the value R0 of the player.
  143.  
  144.     Inputs: mode    - 0 = Simple computation
  145.               1 = Advanced computation (special ratings and
  146.               ratings for players without old rating)
  147. */
  148. static void GetWe(struct DWZ *tDWZ, int mode)
  149.  
  150. { struct Game *g;
  151.   short gdwz, DWZDiff;
  152.  
  153.   /*
  154.       Compute mean value
  155.   */
  156.   tDWZ->n = 0;
  157.   tDWZ->We = tDWZ->W = 0.0;
  158.   tDWZ->Rc = 0;
  159.   for (g = tDWZ->t->First_Game;  g != NULL;  g = g->Next)
  160.   { if (g->Opponent == NULL  ||  (g->Flags & GMFLAGSF_NOFIGHT) != 0  ||
  161.     tdwz(g->Opponent) == 0  ||  g->Result < 0)
  162.     { continue;
  163.     }
  164.     gdwz = tdwz(g->Opponent);
  165.     if (mode == 1  &&
  166.     ((struct DWZ *) g->Opponent->Helpptr)->RH > gdwz + 200  &&
  167.      (tDWZ->R0 == 0  ||  tDWZ->R0 + 200 >= tDWZ->RH))
  168.     { gdwz = ((struct DWZ *) g->Opponent->Helpptr)->RH;
  169.     }
  170.     tDWZ->Rc += gdwz;
  171.     if ((DWZDiff = tDWZ->R0 - gdwz) >= 0)
  172.     { tDWZ->We += (DWZDiff > 735) ? 1.0 : DWZtoPercentTab[DWZDiff];
  173.     }
  174.     else
  175.     { tDWZ->We += (DWZDiff < -735) ? 0.0 : 1.0-DWZtoPercentTab[-DWZDiff];
  176.     }
  177.     tDWZ->W += g->Result/2.0;
  178.     ++tDWZ->n;
  179.   }
  180. }
  181.  
  182.  
  183.  
  184. /*
  185.     The following function computes a players DWZ. See Peter Zoefel,
  186.     Karl-Heinz Glenz; "Das ELO-System", Chapter 10 for the algorithm.
  187.  
  188.     mode = 0:   Simple computation
  189.     mode = 1:   Advanced computation; see GetWe()
  190.  
  191.     Result: 0  = User has terminated
  192.         1  = Don't include player into DWZ-report
  193.         -1 = O.k.
  194. */
  195. static int NewDWZ(struct DWZ *tDWZ, int mode)
  196.  
  197. { struct Player *t = tDWZ->t;
  198.   struct tm now, birthday;
  199.  
  200.   tDWZ->R0 = tdwz(t);
  201.   GetWe(tDWZ, mode);
  202.  
  203.   /*
  204.       Compute DWZ, if possible
  205.   */
  206.   if (tDWZ->n == 0)
  207.   { return(1);
  208.   }
  209.  
  210.  
  211.   if (tdwz(t) != 0)
  212.   { /*
  213.     Compute the new DWZ of a player with existing DWZ. (See "Das
  214.     ELO-System, page 88)
  215.     */
  216.     if (mode == 0)
  217.     { /*
  218.       Get the players age (this is needed for parameter E)
  219.       */
  220.       time_t tmt = clock();
  221.       memcpy(&now, localtime(&tmt), sizeof(now));
  222.  
  223. Loop: if (!atotm(t->BirthDay, &birthday))
  224.       { switch(AskForBirthday(t))
  225.     { case 1:
  226.         tDWZ->J = 5;
  227.         break;
  228.       case 2:
  229.         tDWZ->J = 10;
  230.         break;
  231.       case 3:
  232.         tDWZ->J = 15;
  233.         break;
  234.       case 4:
  235.         if (!ModifyOnePlayer(t, TRUE))
  236.         { return(0);
  237.         }
  238.         goto Loop;
  239.       case 5:
  240.         return(1);
  241.       case 0:
  242.         return(0);
  243.     }
  244.       }
  245.       else
  246.       { birthday.tm_year += 21;
  247.     if (CmpDates(&birthday, &now) > 0)
  248.     { tDWZ->J = 5;
  249.     }
  250.     else
  251.     { birthday.tm_year += 5;
  252.       tDWZ->J = (CmpDates(&birthday, &now) > 0) ? 10 : 15;
  253.     }
  254.       }
  255.     }
  256.     tDWZ->R0 = tdwz(t);
  257.     { double E = tDWZ->R0/1000.0;
  258.       tDWZ->E = floor(0.5+E*E*E*E+tDWZ->J);
  259.     }
  260.     tDWZ->RH = floor(0.5+(800.0*(tDWZ->W-tDWZ->We))/tDWZ->n+tDWZ->R0);
  261.  
  262.     tDWZ->Rn = floor(0.5+(double) (tDWZ->E*tDWZ->R0 + tDWZ->n*tDWZ->RH) /
  263.              (double) (tDWZ->E+tDWZ->n));
  264.   }
  265.   else
  266.   { /*
  267.     Compute new DWZ for a player who wasn't rated yet.
  268.     See "Das ELO-System", page 93)
  269.     */
  270.     int RH;
  271.     struct DWZ tDWZ1, tDWZ2;
  272.     int p;
  273.     double d;
  274.  
  275.     /*
  276.     We cannot compute a DWZ, if the player has 0% or 100%
  277.     */
  278.     if (tDWZ->W == 0.0  ||  tDWZ->W == (double) tDWZ->n)
  279.     { tDWZ->Rn = 0;
  280.       return(-1);
  281.     }
  282.     p = floor(tDWZ->W/tDWZ->n*1000+0.5);
  283.     d = PercentToDWZTab[999-p];
  284.     tDWZ->R0 = floor(0.5+((double)tDWZ->Rc)/((double)tDWZ->n)+d);
  285.  
  286.     /*
  287.     Iterate until RH = tDWZ->RH. This is somewhat complicated
  288.     because we need to suppress endless loops.
  289.     */
  290.     tDWZ1 = *tDWZ;
  291.     tDWZ2 = *tDWZ;
  292.     do
  293.     { RH = tDWZ1.RH;
  294.       GetWe(&tDWZ1, mode);
  295.       tDWZ1.R0 = tDWZ1.RH =
  296.                floor(0.5+tDWZ1.R0+(800*(tDWZ1.W-tDWZ1.We))/tDWZ1.n);
  297.       GetWe(&tDWZ1, mode);
  298.       tDWZ1.R0 = tDWZ1.RH =
  299.                floor(0.5+tDWZ1.R0+(800*(tDWZ1.W-tDWZ1.We))/tDWZ1.n);
  300.       GetWe(&tDWZ2, mode);
  301.       tDWZ2.R0 = tDWZ2.RH =
  302.                floor(0.5+tDWZ2.R0+(800*(tDWZ2.W-tDWZ2.We))/tDWZ2.n);
  303.     }
  304.     while (tDWZ1.RH != RH  &&  tDWZ1.RH != tDWZ2.RH);
  305.     *tDWZ = tDWZ1;
  306.     tDWZ->Rn = tDWZ->RH;
  307.   }
  308.   return(-1);
  309. }
  310.  
  311.  
  312.  
  313.  
  314. /*
  315.     Finally here comes the output function.
  316.  
  317.     Inputs: filename - destination file; see InitOutput()
  318.         device   - output device; see InitOutput()
  319. */
  320. void OutDWZReport(char *filename, int device)
  321.  
  322. { struct Player *t;
  323.   void *DWZMem = NULL;
  324.   struct DWZ *FirstDWZ = NULL, *tDWZ, **DWZptr = &FirstDWZ;
  325.   long l;
  326.   short dwz, i;
  327.   char prthead[162];
  328.   char scrhead[81];
  329.   char line1[81], line2[81];
  330.   char dwzold[20], dwznew[20], dwzhelp[20];
  331.   char We[15];
  332.  
  333.   sprintf(scrhead, "%-30s %-11s %-4s %-3s %-7s %-5s %-11s",
  334.            MSG_NAME_OUTPUT,
  335.            " Ro", " W", "  n", "  We", " RH", " Rn");
  336.   sprintf(prthead, "%-30s %-11s %-4s %-3s %-7s %-5s %-11s\n     (%s)",
  337.            MSG_NAME_OUTPUT, " Ro", " W", "  n",
  338.            "  We", " RH", " Rn", MSG_BIRTHDAY_OUTPUT);
  339.   if (!InitOutput((char *) MSG_DWZ_TITLE, prthead, scrhead,
  340.           filename, "#?.dwz", device, 2, 1))
  341.   { goto Terminate;
  342.   }
  343.  
  344.   /*
  345.       Create list of players for which the DWZ can be computed and do
  346.       the simple computation.
  347.   */
  348.   for (t = (struct Player *) PlayerList.lh_Head;
  349.        t->Tn_Node.ln_Succ != NULL;
  350.        t = (struct Player *) t->Tn_Node.ln_Succ)
  351.   { /*
  352.     Get RAM for player
  353.     */
  354.     if ((tDWZ = GetMem(&DWZMem, sizeof(*tDWZ)))  ==  NULL)
  355.     { goto Terminate;
  356.     }
  357.  
  358.     tDWZ->t = t;
  359.     t->Helpptr = (struct Player *) tDWZ;
  360.     switch (NewDWZ(tDWZ, 0))
  361.     { case 0:
  362.     goto Terminate;
  363.       case 1:
  364.     continue;
  365.     }
  366.     *DWZptr = tDWZ;
  367.     DWZptr = &(tDWZ->Next);
  368.   }
  369.  
  370.   /*
  371.       Special algorithms for players whose RH-number is greater than
  372.       their old rating + 200 points.
  373.   */
  374.   for (tDWZ = FirstDWZ;  tDWZ != NULL;  tDWZ = tDWZ->Next)
  375.   { if (NewDWZ(tDWZ, 1) == 0)
  376.     { goto Terminate;
  377.     }
  378.   }
  379.  
  380.   for (tDWZ = FirstDWZ; tDWZ != NULL;  tDWZ = tDWZ->Next)
  381.   { if ((dwz = tdwz(tDWZ->t)) == 0)
  382.     { sprintf(dwzold, "%11s", "");
  383.       sprintf(dwzhelp, "(%d)", tDWZ->n);
  384.       if (tDWZ->Rn != 0)
  385.       { sprintf(dwznew, "%5d-%-5s", tDWZ->Rn,
  386.             (tDWZ->n > 4) ? "1" : dwzhelp);
  387.       }
  388.       else
  389.       { sprintf(dwznew, "     -%-5s", dwzhelp);
  390.       }
  391.       sprintf(We, "       ");
  392.     }
  393.     else
  394.     { i = StrToLong((STRPTR) tDWZ->t->DWZ, &l);
  395.       if (tDWZ->t->DWZ[i] == '\0'  ||
  396.       StrToLong((STRPTR) tDWZ->t->DWZ+(i+1), &l) < 0)
  397.       { sprintf(dwzold, "%5d      ", dwz);
  398.     sprintf(dwznew, "%5d      ", tDWZ->Rn);
  399.       }
  400.       else
  401.       { sprintf(dwzold, "%5d-%-5ld", dwz, l);
  402.     sprintf(dwznew, "%5d-%-5ld", tDWZ->Rn, l+1);
  403.       }
  404.       sprintf(We, "%7.3lf", tDWZ->We);
  405.     }
  406.  
  407.     sprintf(line1, "%-30s %11s %4.1lf %3d %s %5d %11s",
  408.         tDWZ->t->Name, dwzold, tDWZ->W, tDWZ->n, We, tDWZ->RH,
  409.         dwznew);
  410.     sprintf(line2, (*tDWZ->t->BirthDay != '\0')  ?  "     (%s)"  :  "",
  411.         tDWZ->t->BirthDay);
  412.     if (!lprint(line1)  ||
  413.     (device != DEVICE_Screen  &&  !lprint(line2)))
  414.     { goto Terminate;
  415.     }
  416.   }
  417.  
  418.   ProcessOutput();
  419.  
  420. Terminate:
  421.   TerminateOutput();
  422.   PutMemList(&DWZMem);
  423. }
  424.